home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-01 | 22.9 KB | 854 lines | [TEXT/MPS ] |
- // UStream.cp
- // Copyright © 1990-1991 by Apple Computer Inc. All rights reserved.
- // Originally written by Larry S. Rosenstein. Used by permission
-
- // Types defining the table mapping old class IDs (found in the stream) to new class IDs
- // for the classes linked with the application.
-
- #ifndef __USTREAM__
- #include <UStream.h>
- #endif
-
- #ifndef __GEOMETRY__
- #include <Geometry.h>
- #endif
-
- #ifndef __UFILE__
- #include <UFile.h>
- #endif
-
- #ifndef __UFAILURE__
- #include <UFailure.h>
- #endif
-
- #ifndef __TEXTEDIT__
- #include <TextEdit.h>
- #endif
-
- #ifndef __OSUTILS__
- #include <OSUtils.h>
- #endif
-
- #ifndef __UMACAPPUTILITIES__
- #include <UMacAppUtilities.h>
- #endif
-
- #ifndef __UPATCH__
- #include <UPatch.h>
- #endif
-
- #ifndef __UMEMORY__
- #include <UMemory.h>
- #endif
-
- #ifndef __FILES__
- #include <Files.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif
-
-
- const short kMaxClasses = 8000;
-
- typedef struct ClassIDEntry
- {
- ObjClassID fOldID;
- ObjClassID fNewID;
- };
-
-
- typedef ClassIDEntry ClassArray[kMaxClasses], * PClassIDEntry;
- typedef PClassIDEntry* HClassArray;
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal Boolean TStream::AtEnd(void)
- {
- if (this->GetPosition() >= this->GetSize())
- return TRUE;
- else
- return FALSE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamFields
-
- pascal void TStream::Fields(TObject* obj) // override
- {
- obj->DoToField("TStream", NULL, bClass);
- obj->DoToField("fClassMapSize", &fClassMapSize, bInteger);
- obj->DoToField("fClassMap", &fClassMap, bHandle);
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamFree
-
- pascal void TStream::Free(void) // override
- {
- fClassMap = DisposeIfHandle(fClassMap);
- inherited::Free();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal long TStream::GetPosition(void)
- {
- return 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal long TStream::GetSize(void)
- {
- return 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- pascal void TStream::Initialize(void) // override
-
- {
- inherited::Initialize();
- fClassMap = NULL;
- fClassMapSize = 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- pascal void TStream::IStream(void)
- {
- FailInfo fi;
-
- if (fi.Try()) // In case allocation fails, object is freed.
- {
- this->IObject();
- fClassMap = NewPermHandle(0);
- fi.Success();
- }
- else // Recover
- {
- this->Free(); // Free the stream if it can't be initialized
- fi.ReSignal();
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- // This returns the new class ID given a class ID found
- // in the stream, or kNilClass if it wasn't found.
- // It does a simple linear search.
- pascal ObjClassID TStream::LookupClassID(ObjClassID id)
- {
- if (id != kNilClass)
- for (short i = 0; i < fClassMapSize; ++i)
- if (((ClassArray) * fClassMap)[i].fOldID == id)
- return ((ClassArray) * fClassMap)[i].fNewID;
- return kNilClass;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamNever
-
- pascal void TStream::ReadBytes(void* ,
- long)
- {
- this->SubClassResponsibility();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- // The trick here is that characters are
- // represented as 2 bytes, with the actual
- // data in the low order byte.
- pascal void TStream::ReadCharacter(short& data)
- {
- this->ReadBytes((char*)(&data + 1), 1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- pascal void TStream::ReadInteger(short& data)
- {
- this->ReadBytes(&data, sizeof(short));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- pascal void TStream::ReadLong(long& data)
- {
- this->ReadBytes(&data, sizeof(long));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- pascal void TStream::ReadObject(TObject** data,
- Boolean& known)
- {
- ObjClassID streamID; // Class ID in stream.
- long sizePosition;
- long objectSize;
- MAName className;
- ObjClassID currentID; // Class ID in program.
-
- this->ReadBytes(&streamID, sizeof(ObjClassID));// Read the object's class ID.
-
- sizePosition = this->GetPosition(); // Read its size and remember the current position.
- this->ReadLong(objectSize);
-
- this->ReadString(className, sizeof(MAName));// Read its name.
-
- if (className.IsEmpty()) // No class name. Must have seen the class
- // before, so convert the streamID to the
- // currentID.
- currentID = this->LookupClassID(streamID);
- else
- { // Get ID from name ...
- currentID = GetClassIDFromName(className);
- this->RegisterClassID(streamID, currentID);// ... and register the IDs.
- }
-
- if (currentID == kNilClass) // Don't know about the class.
- {
- *data = NULL;
- // If the streamID is kNilClass then the object was realy
- // NULL, which is a known object, otherwise the class
- // isn't available.
- known = streamID == kNilClass;
-
- // Skip over the object's data.
- this->SetPosition(sizePosition + objectSize);// Skip over its data.
- }
- else
- { // Create the object.
- *data = NULL;
- *data = NewObjectByClassId(currentID);
- known = TRUE;
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- pascal void TStream::ReadPoint(Point& data)
- {
- this->ReadBytes(&data, sizeof(Point));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- pascal void TStream::ReadRect(Rect& data)
- {
- this->ReadBytes(&data, sizeof(Rect));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- pascal void TStream::ReadStreamObject(TObject** data,
- Boolean& known)
- {
- this->ReadObject(data, known); // Create an uninitialized object.
-
- if (*data) // If we got an object, then tell it to initialize itself.
- (*data)->ReadFrom(this);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- pascal void TStream::ReadString(String& data,
- short maxSize)
- {
- this->ReadBytes(&data, 1); // Read the length byte.
-
- if (data.Length() + 1 > maxSize)
- FailOSErr(paramErr); // Can't read that many bytes.
- else
- this->ReadBytes(&data[1], (long)data.Length());
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- // This simply adds the mapping to the end of the list.
- // It does not check to see if the mapping exists already.
- pascal void TStream::RegisterClassID(ObjClassID oldID,
- ObjClassID newID)
- {
- if (oldID != kNilClass)
- {
- ++fClassMapSize;
- SetHandleSize(fClassMap, fClassMapSize * sizeof(ClassIDEntry));
-
- ((ClassArray) * fClassMap)[fClassMapSize].fOldID = oldID;
- ((ClassArray) * fClassMap)[fClassMapSize].fNewID = newID;
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal void TStream::SetPosition(long newPosition)
- {
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal void TStream::SetSize(long newSize)
- {
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void TStream::WriteCharacter(short data)
- {
- this->WriteBytes((char*)(&data + 1), 1); // Again, the data is in the low order byte.
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamNever
-
- pascal void TStream::WriteBytes(const void* ,
- long )
- {
- this->SubClassResponsibility();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void TStream::WriteInteger(short data)
-
- {
- this->WriteBytes(&data, sizeof(short));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void TStream::WriteLong(long data)
-
- {
- this->WriteBytes(&data, sizeof(long));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void TStream::WriteObject(TObject* data,
- long& sizePosition)
- {
- ObjClassID streamID;
- MAName className;
-
- if (data)
- streamID = data->GetClass();
- else
- streamID = kNilClass;
-
- this->WriteBytes(&streamID, sizeof(ObjClassID));// Write the class ID.
-
- sizePosition = this->GetPosition(); // Remember the position of the object size
- // in the stream.
-
- this->WriteLong(MAXLONGINT); // Write a dummy size (maximum object size).
-
- if ((data) && (this->LookupClassID(streamID) == kNilClass))
- // data is not NULL, and this is the first object of the class.
- {
- data->GetClassName(className); // Get the actual class name.
-
- // Register the ID, so we don't write the class name the next time
- // we write an object of this class. The second parameter
- // doesn't matter, as long as it isn't kNilClass.
- this->RegisterClassID(streamID, streamID);
- }
- else
- className = "";
-
- this->WriteString(className); // Write the class name (which may be empty).
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- // This fills in the object's size at the position passed in.
- pascal void TStream::WriteObjectSize(long sizePosition)
- {
- long currentPosition = this->GetPosition(); // Remember where we are.
- this->SetPosition(sizePosition); // Go back to position of size.
-
- this->WriteLong(currentPosition - sizePosition);// Write the size.
-
- this->SetPosition(currentPosition); // Go back to where we were.
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void TStream::WritePoint(Point data)
- {
- this->WriteBytes(&data, sizeof(Point));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void TStream::WriteRect(const Rect& data)
- {
- this->WriteBytes(&data, sizeof(Rect));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void TStream::WriteStreamObject(TObject* data)
- {
- long sizePosition;
-
- this->WriteObject(data, sizePosition); // Write the object header.
-
- if (data) // Write the private data.
- data->WriteTo(this);
-
- this->WriteObjectSize(sizePosition); // Write the object size.
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void TStream::WriteString(const String& data)
- {
- this->WriteBytes(&data, ((long)data.Length()) + 1);// + 1 to include length byte.
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamFields
-
- pascal void TFileStream::Fields(TObject* obj) // override
- {
- obj->DoToField("TFileStream", NULL, bClass);
- obj->DoToField("fFile", &fFile, bObject);
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal long TFileStream::GetPosition(void) // override
- {
- long itsDataMark;
-
- FailNIL(fFile);
- FailOSErr(fFile->GetDataMark(itsDataMark)); // Call the TFile method.
- return itsDataMark; // Return the result.
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal long TFileStream::GetSize(void) // override
- {
- long itsDataLength;
-
- FailNIL(fFile); // ??? or just return 0
- FailOSErr(fFile->GetDataLength(itsDataLength)); // Call the TFile method.
- return itsDataLength; // Return the result.
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- pascal void TFileStream::Initialize(void) // override
- {
- inherited::Initialize();
-
- fFile = NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- pascal void TFileStream::IFileStream(TFile* itsFile)
- {
- this->IStream();
- fFile = itsFile; // Remember the file reference.
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal void TFileStream::SetPosition(long newPosition)// override
- {
- FailNIL(fFile);
- FailOSErr(fFile->SetDataMark(newPosition,fsFromStart));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal void TFileStream::SetSize(long newSize) // override
- {
- FailNIL(fFile);
- FailOSErr(fFile->SetDataLength(newSize));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- pascal void TFileStream::ReadBytes(void* p,
- long count) // override
- {
- FailNIL(fFile);
- FailOSErr(fFile->ReadData(p,count));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void TFileStream::WriteBytes(const void* p,
- long count) // override
- {
- FailNIL(fFile);
- FailOSErr(fFile->WriteData(p,count));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamFields
-
- pascal void THandleStream::Fields(TObject* obj) // override
- {
- obj->DoToField("THandleStream", NULL, bClass);
- obj->DoToField("fHandle", &fHandle, bInteger);
- obj->DoToField("fPosition", &fPosition, bLongInt);
- obj->DoToField("fSize", &fSize, bLongInt);
- obj->DoToField("fGrowthSize", &fGrowthSize, bLongInt);
-
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamFree
-
- pascal void THandleStream::Free(void) // override
- {
- this->SetSize(this->GetPosition()); // Trim the handle to its current position.
- inherited::Free();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal long THandleStream::GetPosition(void) // override
- {
- return fPosition;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal long THandleStream::GetSize(void) // override
- {
- return fSize;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal long THandleStream::GrowthSize(long needed)
- {
- return Max(fGrowthSize, needed);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- pascal void THandleStream::Initialize(void) // override
- {
- inherited::Initialize();
-
- fGrowthSize = 1;
- fHandle = NULL;
- fPosition = 0;
- fSize = 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- pascal void THandleStream::IHandleStream(Handle itsHandle,
- long growth)
- {
- this->IStream();
-
- fHandle = itsHandle;
- fGrowthSize = growth;
- fPosition = 0;
- fSize = GetHandleSize(itsHandle);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal void THandleStream::SetPosition(long newPosition)// override
- {
- OSErr err;
-
- if (newPosition < 0) // Same error returned by File Manager.
- FailOSErr(posErr);
- else if (newPosition > fSize) // Hit the end of the stream.
- {
- newPosition = fSize; // We still want to position to end of the stream.
- err = eofErr;
- }
- else
- err = noErr;
-
- fPosition = newPosition;
- FailOSErr(err);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal void THandleStream::SetSize(long newSize)// override
- {
- SetHandleSize(fHandle, newSize);
- FailMemError(); // Signal failure if we got a Memory Manager error.
-
- if (newSize < fPosition) // If we shrunk the size, then we have to adjust the position.
- fPosition = newSize;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- pascal void THandleStream::ReadBytes(void* p,
- long count)// override
- {
- long available;
- OSErr err;
-
- available = fSize - fPosition; // Bytes available in the stream.
-
- if (available < count) // About to read past end of stream.
- {
- count = available;
- err = eofErr;
- }
- else
- err = noErr;
-
- if (count > 0) // Move the bytes.
- {
- BlockMove((Ptr)(*fHandle + fPosition), (Ptr)p, count);
- fPosition += count;
- }
- else if (count < 0)
- err = paramErr; // Negative request count.
-
- FailOSErr(err);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void THandleStream::WriteBytes(const void* p,
- long count)// override
- {
- long available;
-
- if (count < 0)
- FailOSErr(paramErr); // Negtive request count.
-
- available = fSize - fPosition; // Bytes available in the stream.
-
- if (available < count) // Grow the handle to accommodate request.
- this->SetSize(fSize + this->GrowthSize(count - available));
-
- BlockMove(p, (Ptr)(*fHandle + fPosition), count); // Move the bytes.
-
- fPosition += count; // Advance the position.
-
- if (fPosition > fSize) // Adjust the size if necessary.
- fSize = fPosition;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamFields
-
- pascal void TCountingStream::Fields(TObject* obj)// override
- {
- obj->DoToField("TCountingStream", NULL, bClass);
- obj->DoToField("fPosition", &fPosition, bLongInt);
- obj->DoToField("fSize", &fSize, bLongInt);
-
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal long TCountingStream::GetSize(void) // override
- {
- return fPosition;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- pascal void TCountingStream::Initialize(void) // override
- {
- inherited::Initialize();
- fPosition = 0;
- fSize = 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- pascal void TCountingStream::ICountingStream(void)
- {
- this->IStream();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamWrite
-
- pascal void TCountingStream::WriteBytes(const void* /* p */,
- long count)// override
- {
- if (count < 0) // Can't write negative number of bytes.
- FailOSErr(paramErr);
-
- fPosition += count; // Advance the position.
-
- if (fPosition > fSize) // Adjust the size if necessary.
- fSize = fPosition;
- }
-
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- pascal void TResourceStream::Initialize(void) // override
- {
- inherited::Initialize();
-
- fResource = NULL;
- fPosition = 0;
- fSize = 0;
- }
-
- //--------------------------------------------------------------------------------
- #pragma segment MAStreamCreate
-
- pascal void TResourceStream::IResourceStream(ResType theType, short theID)
- {
- if (gConfiguration.systemVersion >= 0x700)
- {
- this->IStream();
-
- Boolean oldResLoad = GetResLoad();
- SetResLoad(FALSE);
- fResource = GetResource(theType, theID);
- SetResLoad(oldResLoad);
- FailNILResource(fResource);
- fSize = SizeResource(fResource);
- FailResError();
- }
- else // The services in this stream are only available under System 7, so…
- Failure(minErr, 0); // !!! need to assign an error constant
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal long TResourceStream::GetPosition(void) // override
- {
- return fPosition;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal void TResourceStream::SetPosition(long newPosition)// override
- {
- fPosition = newPosition;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal long TResourceStream::GetSize(void)
- {
- return fSize;
- /*
- It's better to maintain our own size, in fSize, than to call SizeResource().
-
- long itsSize = SizeResource(fResource);
- FailResError();
- return itsSize;
- */
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamUtil
-
- pascal void TResourceStream::SetSize(long newSize)// override
- {
- fSize = newSize;
- SetResourceSize(fResource, newSize);
- FailResError();
-
- if (newSize < fPosition) // If we shrunk the size, then we have to adjust the position.
- fPosition = newSize;
- }
-
- //--------------------------------------------------------------------------------
- #pragma segment MASectionWrite
-
- pascal void TResourceStream::WriteBytes(const void* p, long count)
- {
- register long minSize = this->GetPosition() + count;
- if (minSize > this->GetSize())
- this->SetSize(minSize); // increase the size before writing
- WritePartialResource(fResource, this->GetPosition(), p, count);
- FailResError();
-
- this->SetPosition(minSize); // Advance the position.
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAStreamRead
-
- pascal void TResourceStream::ReadBytes(void* p, long count) // override
- {
- register long minToRead = Min(count, this->GetSize() - this->GetPosition());
- ReadPartialResource(fResource, this->GetPosition(), p, minToRead);
- FailResError();
-
- this->SetPosition(this->GetPosition() + count); // Advance the position.
- }
-
-